package com.immortal.core.module.version.core;

import com.immortal.core.module.version.annotation.ApiVersion;
import com.immortal.core.module.version.annotation.ClientVersion;
import com.immortal.core.module.version.condition.ClientVersionRequestCondition;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.web.servlet.mvc.condition.RequestCondition;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.lang.reflect.Method;

/**
 * <p>TODO
 *
 * @author wind
 * @version 1.0
 * @since 2018/12/19
 */
public class CustomRequestMappingHandlerMapping extends RequestMappingHandlerMapping {

    @Override
    protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
        RequestMappingInfo mappingInfo = super.getMappingForMethod(method, handlerType);
        if (mappingInfo != null) {
            RequestMappingInfo apiVersionMappingInfo = getApiVersionMappingInfo(method, handlerType);
            return apiVersionMappingInfo == null ? mappingInfo : apiVersionMappingInfo.combine(mappingInfo);
        }
        return mappingInfo;

    }

    @Override
    protected RequestCondition<?> getCustomTypeCondition(Class<?> handlerType) {
        ClientVersion clientVersion = AnnotatedElementUtils.findMergedAnnotation(handlerType, ClientVersion.class);
        return createRequestCondition(clientVersion);
    }

    @Override
    protected RequestCondition<?> getCustomMethodCondition(Method method) {
        ClientVersion clientVersion = AnnotatedElementUtils.findMergedAnnotation(method, ClientVersion.class);
        return createRequestCondition(clientVersion);
    }

    private RequestCondition<?> createRequestCondition(ClientVersion clientVersion) {
        if (clientVersion == null) {
            return null;
        }
        if (clientVersion.value() != null && clientVersion.value().length > 0) {
            return new ClientVersionRequestCondition(clientVersion.value());
        }
        if (clientVersion.expression() != null && clientVersion.expression().length > 0) {
            return new ClientVersionRequestCondition(clientVersion.expression());
        }
        return null;
    }

    private RequestMappingInfo getApiVersionMappingInfo(Method method, Class<?> handlerType) {
        //优先查找method
        ApiVersion apiVersion = AnnotatedElementUtils.findMergedAnnotation(method, ApiVersion.class);
        if (apiVersion == null || StringUtils.isBlank(apiVersion.value())) {
            apiVersion = AnnotatedElementUtils.findMergedAnnotation(handlerType, ApiVersion.class);
        }
        return apiVersion == null || StringUtils.isBlank(apiVersion.value()) ? null : RequestMappingInfo
                .paths(apiVersion.value())
                .build();
    }
}
